;; another obo to owl converter

;; (setq obo (make-instance 'obo :path "~/repos/ogms/trunk/src/ontology/ogms.obo"))
;; (read-obo obo)
;; (ogms-to-owl obo) -> ~/Desktop/ogms.owl

(defun getf-multiple (plist indicator)
  (loop for (key value) on plist by #'cddr when (eq indicator key) collect value))

(defun ogms-to-owl (obo &optional (dest "ogms:ontology;ogms.owl"))
  (flet ((uri-ify (id)
	   (cond ((equal id "BFO:0000076")
		  !bfo:Entity)
		 ((#"matches" id "^BFO:.*")
		  (make-uri (second (assoc id *bfo-map* :test 'equalp))))
		 ((#"matches" id "^OGMS:.*")
		  (make-uri (#"replaceFirst" id "OGMS:" "http://purl.obolibrary.org/obo/OGMS_")))
		 ((#"matches" id "^OBO_REL:.*")
		  (make-uri (#"replaceFirst" id "^OBO_REL:" "http://www.obofoundry.org/ro/ro.owl#")))
		 ((#"matches" id "^IAO:.*")
		  (make-uri (#"replaceFirst" id "^IAO:" "http://purl.obolibrary.org/obo/IAO_")))
		 (t (error "don't know how to convert id ~a to uri" id)))))
    (with-ontology ogms (:about "http://purl.obolibrary.org/obo/ogms.owl" :base "http://purl.obolibrary.org/obo/ogms.owl")
	((owl-imports !<http://www.ifomis.org/bfo/1.1>)
	 (owl-imports !<http://purl.obolibrary.org/obo/iao/ontology-metadata.owl>)
	 (owl-imports !<http://protege.stanford.edu/plugins/owl/dc/protege-dc.owl>)
	 (ontology-annotation !rdfs:comment "The Ontology for General Medical Science (OGMS) is based on the papers Toward an Ontological Treatment of Disease and Diagnosis and On Carcinomas and Other Pathological Entities. The ontology attempts to address some of the issues raised at the Workshop on Ontology of Diseases (Dallas, TX). OGMS was formerly called the clinical phenotype ontology. Terms from OGMS hang from the Basic Formal Ontology.

The latest version of OGMS is always available at http://purl.obolibrary.org/obo/ogms.owl
This is version 2009-12-03 aka '0.3'
http://purl.obolibrary.org/obo/ogms/2009-12-09/ogms.owl

The OGMS developer site is http://code.google.com/p/ogms/
The discussion group is http://groups.google.com/group/ogms-discuss

If you are interested in participating in the development of OGMS, please send email to albertgoldfain@gmail.com. Be sure to include a google-account username with your request (this will be the username associated with a gmail address).")
	 (ontology-annotation !rdfs:comment "This ontology is in early development. Expect it to change.")
	 (ontology-annotation !dc:creator "Richard Scheuermann")
	 (ontology-annotation !dc:creator "Barry Smith")
	 (ontology-annotation !dc:creator "Werner Ceusters")
	 (ontology-annotation !dc:creator "Albert Goldfain")
	 (ontology-annotation !dc:creator "Lindsay Cowell")
	 (ontology-annotation !dc:creator "Anand Kumar")
	 (ontology-annotation !dc:creator "Cornelius Rosse")
	 (ontology-annotation !dc:creator "Bill Hogan")
	 (ontology-annotation !dc:creator "Sivaram Arabandi")
	 (ontology-annotation !dc:creator "Bill Hogan")
	 (ontology-annotation !dc:creator "Daniel Merico")
	 (ontology-annotation !dc:creator "Alan Ruttenberg")
	 (annotation-property !obo:IAO_0000115 (label "definition"))
	 (annotation-property !obo:IAO_0000117 (label "definition editor"))
	 (annotation-property !obo:IAO_0000119 (label "definition source"))
	 (annotation-property !obo:IAO_0000116 (label "editor note"))
	 (annotation-property !obo:IAO_0000232 (label "curator note"))
	 (ontology-annotation !dc:date (literal "2009-08-07" !xsd:date))
	 (loop for record in (terms obo) 
	    for name = (getf (cdr record) :name)
	    for id = (getf (cdr record) :id)
	    for is_a = (getf-multiple (cdr record) :is_a)
	    for xrefs = (getf-multiple (cdr record) :xref)
	    for def = (getf (cdr record) :def)
	    for created-by = (getf (cdr record) :created_by)
	    for creation-date = (getf (cdr record) :creation_date)
	    if (equal name "undefined primitive terms") do (setq name "_undefined primitive term")
	    unless (or (equal id !owl:Thing) (equal id !bfo:Entity) (#"matches" id "BFO.*") (equal id "OGMS:0000072"))
	    collect (apply 'class (unless (#"matches" id "IAO.*") (label name)) (uri-ify id)
			   (if (car def) (annotation !obo:IAO_0000115 (literal (car def)  :|@en|)))
			   (if (third def) (annotation !obo:IAO_0000119  (third def)))
			   (if created-by (annotation !obi:IAO_0000117 (#"replaceAll" created-by "agoldfain" "Albert Goldfain")))
			   (if creation-date (annotation !obo:IAO_0000232 (format nil "creation date: ~a" creation-date)))
			   (if (member "BFO:0000076" is_a :test 'equalp)
			       (annotation !obi:IAO_0000116 "note: defined class"))
			   (append
			    (if (car xrefs)
				(loop for xref in xrefs collect
				    (annotation !oboinowl:hasDbXref (format nil "~a" xref))))
			    (list :partial)
			     (if (getf (cdr record) :is_obsolete)
			       (list !oboinowl:ObsoleteClass)
			       (mapcar #'uri-ify is_a))))))
      (write-rdfxml ogms dest))))

(defun ogms-convert (&optional (source "ogms:ontology;ogms.obo") (dest "ogms:ontology;ogms.owl"))
  (let ((obo (make-instance 'obo :path source)))
    (read-obo obo)
    (ogms-to-owl obo dest)))

(defparameter *bfo-map* 
  '(("BFO:0000000" "http://www.ifomis.org/bfo/1.1#Entity")
   ("BFO:0000001" "http://www.ifomis.org/bfo/1.1/snap#Continuant")
   ("BFO:0000003" "http://www.ifomis.org/bfo/1.1/snap#DependentContinuant")
   ("BFO:0000004" "http://www.ifomis.org/bfo/1.1/snap#IndependentContinuant")
   ("BFO:0000005" "http://www.ifomis.org/bfo/1.1/snap#GenericallyDependentContinuant")
   ("BFO:0000006" "http://www.ifomis.org/bfo/1.1/snap#SpecificallyDependentContinuant")
   ("BFO:0000007" "http://www.ifomis.org/bfo/1.1/snap#Quality")
   ("BFO:0000008" "http://www.ifomis.org/bfo/1.1/snap#RealizableEntity")
   ("BFO:0000009" "http://www.ifomis.org/bfo/1.1/snap#Disposition")
   ("BFO:0000010" "http://www.ifomis.org/bfo/1.1/snap#Role")
   ("BFO:0000011" "http://www.ifomis.org/bfo/1.1/snap#Function")
   ("BFO:0000012" "http://www.ifomis.org/bfo/1.1/snap#Capability")
   ("BFO:0000041" "http://www.ifomis.org/bfo/1.1/snap#MaterialEntity")
   ("BFO:0000042" "http://www.ifomis.org/bfo/1.1/snap#FiatObjectPart")
   ("BFO:0000043" "http://www.ifomis.org/bfo/1.1/snap#Object")
   ("BFO:0000044" "http://www.ifomis.org/bfo/1.1/snap#ObjectAggregate")
   ("BFO:0000002" "http://www.ifomis.org/bfo/1.1/span#Occurrent")
   ("BFO:0000052" "http://www.ifomis.org/bfo/1.1/span#ProcessualEntity")
   ("BFO:0000053" "http://www.ifomis.org/bfo/1.1/span#FiatProcessPart")
   ("BFO:0000058" "http://www.ifomis.org/bfo/1.1/span#Process")
   ("BFO:0000062" "http://www.ifomis.org/bfo/1.1/span#ProcessAggregate")))